package com.sec.etech.form.cust.service;

import cn.hutool.core.date.DateUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.sec.etech.form.cust.gencode.EtechGenCodeUtil;
import org.apache.commons.io.IOUtils;
import org.openbpm.base.api.exception.BusinessException;
import org.openbpm.base.core.util.StringUtil;
import org.openbpm.bus.api.model.IBusTableRel;
import org.openbpm.bus.api.model.IBusinessObject;
import org.openbpm.bus.api.service.IBusinessDataService;
import org.openbpm.bus.api.service.IBusinessObjectService;
import org.openbpm.bus.api.service.IBusinessTableService;
import org.openbpm.form.generatecode.GenCodeConfig;
import org.openbpm.form.generatecode.GenCodeConfigs;
import org.openbpm.form.generatecode.GenCodeUtil;
import org.openbpm.form.manager.FormDefManager;
import org.openbpm.form.model.FormDef;
import org.openbpm.sys.api.freemark.IFreemarkerEngine;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import javax.xml.bind.JAXBContext;
import javax.xml.bind.Unmarshaller;
import java.io.ByteArrayInputStream;
import java.io.InputStream;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Component
public class EtechGenCodeService {
  protected Logger LOG = LoggerFactory.getLogger(getClass());

  @Autowired
  IBusinessDataService businessDataService;

  @Autowired
  IBusinessObjectService businessObjectService;

  @Autowired
  FormDefManager formDefManager;

  @Autowired
  IBusinessTableService businessTableService;

  @Autowired
  IFreemarkerEngine freemarkEngine;

  @Autowired
  EtechGenCodeUtil genCodeUtil;

  public Map<String, String> genCode(JSONObject data) {
    List<FormDef> formDefList = JSON.parseArray(data.getString("formList"), FormDef.class);
    List<GenCodeConfig> genCodeConfigList = getGencodeConfig();
    Map<String, Object> param = (Map<String, Object>)data.toJavaObject(Map.class);
    param.put("genCodeUtil", this.genCodeUtil);
    param.put("currentDate", DateUtil.now());
    param.put("packageFolder", param.get("package").toString().replace(".", "\\"));
    //module?
    Map<String, String> genCodeStr = new HashMap<>();
    for (FormDef formDef : formDefList) {
      IBusinessObject businessObject = this.businessObjectService.getFilledByKey(formDef.getBoKey());
      FormDef form = this.formDefManager.getByKey(formDef.getKey());
      param.put("formHtml", form.getHtml());
      param.put("formKey", formDef.getKey());
      for (GenCodeConfig config : genCodeConfigList) {
        try {
          Map<String, String> codes = genTemplateCode(config, businessObject.getRelation(), param);
          genCodeStr.putAll(codes);
        } catch (Exception e) {
          e.printStackTrace();
          throw new BusinessException(String.format("%s 生成 %s 代码失败", new Object[] { businessObject.getDesc(), config.getName() }));
        }
      }
    }
    return genCodeStr;
  }

  private Map<String, String> genTemplateCode(GenCodeConfig config, IBusTableRel relation, Map<String, Object> param) {
    Map<String, String> files = new HashMap<>();
    param.put("relation", relation);
    String code = this.freemarkEngine.parseByString(config.getTemplate(), param);
    String fileName = relation.getUpperFirstTableKey().concat(config.getFileName());
    if (config.getFileName().indexOf("list") != -1)
      fileName = StringUtil.lowerFirst(fileName);
    String dir = config.getDir().replace("$package", param.get("packageFolder").toString());
    files.put(dir + fileName, code);
    if (!config.getGensub().booleanValue())
      return files;
    for (IBusTableRel child : relation.getChildren()) {
      Map<String, String> childFile = genTemplateCode(config, child, param);
      files.putAll(childFile);
    }
    return files;
  }

  private List<GenCodeConfig> getGencodeConfig() {
    try {
      InputStream instream = getClass().getResourceAsStream("/template/generatecode/genCodeConfig.xml");
      String xml = IOUtils.toString(instream, "UTF-8");
      JAXBContext jAXBContext = JAXBContext.newInstance(new Class[] { GenCodeConfigs.class });
      Unmarshaller unmarshaller = jAXBContext.createUnmarshaller();
      InputStream is = new ByteArrayInputStream(xml.getBytes("utf-8"));
      GenCodeConfigs configs = (GenCodeConfigs)unmarshaller.unmarshal(is);
      for (GenCodeConfig config : configs.getConfigList()) {
        InputStream inputStream = getClass().getResourceAsStream(config.getTplLocation());
        if (inputStream == null)
          throw new BusinessException("File not found： " + config.getTplLocation());
        String template = IOUtils.toString(inputStream, "UTF-8");
        config.setTemplate(template);
      }
      return configs.getConfigList();
    } catch (Exception e) {
      e.printStackTrace();
      throw new BusinessException("解析代码配置失败", e);
    }
  }
}
